package com.ld.control.business.record.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ld.control.business.equipment.service.EquipmentMethodTmpService;
import com.ld.control.business.process.model.ProcessExampleModel;
import com.ld.control.business.process.model.ProcessNodeExampleModel;
import com.ld.control.business.process.model.ProcessNodeExampleRunningModel;
import com.ld.control.business.process.model.ext.ProcessNodeExampleInfoExt;
import com.ld.control.business.process.service.ProcessExampleService;
import com.ld.control.business.process.service.ProcessNodeExampleRunningService;
import com.ld.control.business.process.service.ProcessNodeExampleService;
import com.ld.control.business.record.mapper.ErrorNoticeRecordMapper;
import com.ld.control.business.record.model.ErrorNoticeRecordModel;
import com.ld.control.business.record.service.ErrorNoticeRecordService;
import com.ld.control.business.record.vo.resp.ErrorNoticeRecordRespVo;
import com.ld.control.business.task.model.SubTaskExampleModel;
import com.ld.control.business.task.model.TaskExampleModel;
import com.ld.control.business.task.service.SubTaskExampleService;
import com.ld.control.business.task.service.TaskExampleService;
import com.ld.control.common.CommonConstant;
import com.ld.control.properties.LDProperties;
import com.ld.control.sysenum.ErrorNoticeRecordStatusEnum;
import com.ld.control.sysenum.TaskStatusEnum;
import com.ld.control.utils.JWTUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.Date;

/**
 * <p>
 * 任务报错后的记录和处理 服务实现类
 * </p>
 *
 * @author wangfeng
 * @since 2024-05-13
 */
@Service
public class ErrorNoticeRecordServiceImpl extends ServiceImpl<ErrorNoticeRecordMapper, ErrorNoticeRecordModel> implements ErrorNoticeRecordService {

    @Autowired
    private ErrorNoticeRecordMapper errorNoticeRecordMapper;

    @Autowired
    private ProcessNodeExampleRunningService processNodeExampleRunningService;

    @Autowired
    private TaskExampleService taskExampleService;

    @Autowired
    private SubTaskExampleService subTaskExampleService;

    @Autowired
    private ProcessExampleService processExampleService;

    @Autowired
    private ProcessNodeExampleService processNodeExampleService;

    @Autowired
    private JWTUtils jwtUtils;

    @Autowired
    private EquipmentMethodTmpService equipmentMethodTmpService;

    @Autowired
    private LDProperties ldProperties;


    @Override
    public IPage<ErrorNoticeRecordRespVo> getPageList(String taskExampleCode, Integer status, Integer current, Integer size) {
        IPage<ErrorNoticeRecordRespVo> iPage = new Page<>(current, size);
        return errorNoticeRecordMapper.selectPageList(iPage, taskExampleCode, status);
    }

    @Override
    public void add(ErrorNoticeRecordModel errorNoticeRecordModel) {
        ProcessNodeExampleRunningModel processNodeExampleRunningModel = processNodeExampleRunningService.getById(errorNoticeRecordModel.getProcessNodeExampleRunningId());
        // 查询节点信息
        ProcessNodeExampleInfoExt processNodeExampleModelExt = processNodeExampleService.getProcessNodeExampleModelExt(processNodeExampleRunningModel.getProcessNodeExampleId());
        TaskExampleModel taskExampleModel = processNodeExampleModelExt.getTaskExampleModel();
        SubTaskExampleModel subTaskExampleModel = processNodeExampleModelExt.getSubTaskExampleModel();
        ProcessExampleModel processExampleModel = processNodeExampleModelExt.getProcessExampleModel();

        errorNoticeRecordModel.setTaskExampleCode(taskExampleModel.getCode());
        errorNoticeRecordModel.setTaskExampleName(taskExampleModel.getName());
        if (!ObjectUtils.isEmpty(subTaskExampleModel)) {
            errorNoticeRecordModel.setSubTaskExampleName(subTaskExampleModel.getName());
        }
        errorNoticeRecordModel.setProcessExampleName(processExampleModel.getName());
        errorNoticeRecordModel.setProcessNodeExampleName(processNodeExampleModelExt.getNodeName());
        errorNoticeRecordModel.setCreateTime(new Date());
        errorNoticeRecordModel.setStatus(ErrorNoticeRecordStatusEnum.UNPROCESSED.getStatus());
        errorNoticeRecordModel.setHandleType(CommonConstant.ERROR_HANDLE_TYPE.UNTREATED);
        errorNoticeRecordMapper.insert(errorNoticeRecordModel);
    }

    @Override
    public void retry(Long id) {
        Long processNodeExampleRunningId = getProcessNodeExampleRunningId(id);
        ProcessNodeExampleRunningModel processNodeExampleRunningModel = processNodeExampleRunningService.getById(processNodeExampleRunningId);
        Long processNodeExampleId = processNodeExampleRunningModel.getProcessNodeExampleId();
        Long processExampleId = processNodeExampleRunningModel.getProcessExampleId();
        ProcessNodeExampleInfoExt processNodeExampleModelExt = processNodeExampleService.getProcessNodeExampleModelExt(processNodeExampleId);
        Long taskExampleId = processNodeExampleModelExt.getProcessExampleModel().getTaskExampleId();
        Long subTaskExampleId = processNodeExampleModelExt.getProcessExampleModel().getSubTaskExampleId();
        // 任务变成运行中
        taskExampleService.updateStatus(taskExampleId, TaskStatusEnum.RUNNING.getStatus());
        if (subTaskExampleId != null) {
            // 子任务变成运行中
            subTaskExampleService.updateStatusByNodeId(subTaskExampleId, TaskStatusEnum.RUNNING.getStatus());
        }
        // 流程变成运行中
        processExampleService.updateStatus(processExampleId, TaskStatusEnum.RUNNING.getStatus());
        // 节点变成运行中
        processNodeExampleService.updateNodeStatus(processNodeExampleId, TaskStatusEnum.RUNNING.getStatus());
        // 发送命令给设备
        processNodeExampleRunningService.sendCommand(processNodeExampleRunningId);
    }

    @Override
    public void debugRetry(Long processNodeExampleRunningId) {
        // 发送命令给设备
        processNodeExampleRunningService.sendCommand(processNodeExampleRunningId);
    }

    @Override
    public void skip(Long id) {
        Long processNodeExampleRunningId = getProcessNodeExampleRunningId(id);
        ProcessNodeExampleRunningModel processNodeExampleRunningModel = processNodeExampleRunningService.getById(processNodeExampleRunningId);
        Long processNodeExampleId = processNodeExampleRunningModel.getProcessNodeExampleId();
        ProcessNodeExampleModel processNodeExampleModel = processNodeExampleService.getById(processNodeExampleId);
        if (processNodeExampleModel.getStatus() != TaskStatusEnum.SUCCESS.getStatus()) {
            // 节点变成跳过
            processNodeExampleService.updateNodeStatus(processNodeExampleId, TaskStatusEnum.SKIP.getStatus());
        }
        // 运行下一个节点
        processNodeExampleService.runNextNode(processNodeExampleId);
    }

    @Override
    public void errorHandle(Long id, Integer handleType) {
        // 消除警报
        equipmentMethodTmpService.setErrorAlarm(ldProperties.getDrive().getErrorNoticeEquipmentCode(), "0000");
        Long currentUserAccountId = jwtUtils.getCurrentUserAccountId();
        if (handleType == CommonConstant.ERROR_HANDLE_TYPE.RETRY) {
            retry(id);
        }
        if (handleType == CommonConstant.ERROR_HANDLE_TYPE.SKIP) {
            skip(id);
        }
        // 将错误状态改成已处理
        ErrorNoticeRecordModel errorNoticeRecordModel = errorNoticeRecordMapper.selectById(id);
        errorNoticeRecordModel.setId(id);
        errorNoticeRecordModel.setStatus(ErrorNoticeRecordStatusEnum.PROCESSED.getStatus());
        errorNoticeRecordModel.setHandleType(handleType);
        errorNoticeRecordModel.setUpdateBy(currentUserAccountId);
        errorNoticeRecordModel.setUpdateTime(new Date());
        errorNoticeRecordMapper.updateById(errorNoticeRecordModel);
    }

    @Override
    public Integer getErrorCount() {
        QueryWrapper<ErrorNoticeRecordModel>  queryWrapper= new QueryWrapper<>();
        queryWrapper.eq(ErrorNoticeRecordModel.STATUS, 0);
        Long count = errorNoticeRecordMapper.selectCount(queryWrapper);
        return count.intValue();
    }

    /**
     * 根据错误记录id获取runningId
     * @param id
     * @return
     */
    private Long getProcessNodeExampleRunningId(Long id) {
        Long currentUserAccountId = jwtUtils.getCurrentUserAccountId();
        ErrorNoticeRecordModel errorNoticeRecordModel = errorNoticeRecordMapper.selectById(id);
        return errorNoticeRecordModel.getProcessNodeExampleRunningId();
    }
}
